package com.katze.common.socket;

import com.katze.common.env.AppEnvironment;
import com.katze.common.socket.client.SocketHeartBeatClient;
import com.katze.common.socket.server.SocketCommandRunnable;
import com.katze.common.socket.server.SocketServerManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

import java.net.InetSocketAddress;

/**
 * 项目心跳功能
 * @Params 1.通过手动ping判断客户端项目是否在线
 * @Params  2.客户项目启动时主动向服务端发送上下线指令
 */
public class SocketAutoConfiguration {

    private static final Logger log = LoggerFactory.getLogger(SocketAutoConfiguration.class);

    @Value("${server.address:#{systemProperties['local.address']}}")
    private String local;

    @Value("${server.port}")
    private Integer port;

    /**
     * 客户端启动时自动向服务端发送上线指令，以便服务端时时改变模块运行状态
     * @param remote 服务端地址（IP地址:端口号）
     */
    @ConditionalOnProperty(prefix = "server", name = "ping")
    @Bean(initMethod = "initialization", destroyMethod = "destroy")
    public SocketHeartBeatClient socketClient(@Value("${server.ping}") String remote) {
        String[] items = remote.split(":");
        InetSocketAddress address = new InetSocketAddress(items[0], Integer.parseInt(items[1]));
        SocketHeartBeatClient client = new SocketHeartBeatClient(address);
        client.active(()-> AppEnvironment.APP_NAME.getValue() + ":" + local + ":" + port);
        return client;
    }

    /**
     * 服务端项目/客户端项目之间收发指令
     * @param context Application上下文
     */
    @Bean(destroyMethod = "destroy")
    public SocketServerManager commandSocketServer(ApplicationContext context) {
        SocketServerManager server = new SocketServerManager();
        server.initialization(port - 100, sk -> new SocketCommandRunnable(sk, v-> {
            log.debug("正在执行,指令：{}", v.toString());
            // 扩展逻辑，判断是否为运行状态改变指令（online：在线  offline：下线）
            if (v.getOperate().endsWith("line")) {
                try {
                    HeartBeatHandle handle = context.getBean(HeartBeatHandle.class);
                    String[] items = v.getContent().split(":");
                    handle.changedStatus(items[0], items[1] + ":" + items[2], "offline".equals(v.getOperate())? 1:2);
                } catch (Exception e) {
                    log.warn("状态变更失败", e);
                }
            }
        }));
        return server;
    }

}
